package domaine;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Table(schema = "FINITO", name = "PLATEAUX_PIZZA")
public class PlateauPizza implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7035997730081710089L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "ID_PLATEAU")
	private int idPlateau;

	@NotNull
	@Column(name = "EST_GAGNANT")
	private boolean estGagnant;

	@NotNull
	@Column(name = "NB_MISE_A_JOUR")
	private int nbMiseAJour;

	@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE,
			CascadeType.DETACH })
	@MapKeyColumn(name = "NUM_EMPLACEMENT")
	@JoinTable(schema = "FINITO", name = "EMPLACEMENTS", joinColumns = { @JoinColumn(name = "ID_PLATEAU") }, inverseJoinColumns = { @JoinColumn(name = "NUM_INGREDIENT") })
	private Map<Integer, Ingredient> casesRemplies = new HashMap<Integer, Ingredient>();

	public PlateauPizza() {
	}

	public int getIdPlateau() {
		return idPlateau;
	}

	public boolean estGagnant() {
		return estGagnant;
	}

	public Map<Integer, Ingredient> getCasesRemplies() {
		return casesRemplies;
	}

	public int getNbMiseAJour() {
		return nbMiseAJour;
	}

	boolean remplirCase(int emplacement, Ingredient ingredient) {
		if (casesRemplies.containsKey(emplacement))
			return false;

		casesRemplies.put(emplacement, ingredient);
		nbMiseAJour++;
		return true;
	}

	boolean changerDeCase(int ancienEmplacement, int nouvelEmplacement) {
		if (!casesRemplies.containsKey(ancienEmplacement))
			return false;

		if (casesRemplies.containsKey(nouvelEmplacement))
			return false;

		Ingredient ingredient = casesRemplies.get(ancienEmplacement);

		casesRemplies.remove(ancienEmplacement);
		casesRemplies.put(nouvelEmplacement, ingredient);
		nbMiseAJour++;

		return true;
	}

	public int premiereCaseLibre(boolean regarderAGauche, int numCase) {
		if (numCase < 1 || numCase > 20)
			return -1;

		int position = 0;

		if (numCase < 3)
			position = numCase;

		else if (numCase < 19) {
			position = numCase * 2 - 3;
			if (regarderAGauche)
				position++;
		} else
			position = 36 - (20 - numCase);

		return laPremiereCaseLibre(regarderAGauche, position);
	}

	private int laPremiereCaseLibre(boolean regarderAGauche, int position) {
		if (position < 0 || position > 36)
			return -1;

		if (!casesRemplies.containsKey(position))
			return position;

		int deplaceur = regarderAGauche ? -1 : 1;
		return laPremiereCaseLibre(regarderAGauche, position + deplaceur);
	}

	public int calculerScore() {

		int suiteMax = 0;
		int uneSuite = 0;
		int dernierNumIngredientLu = 0;
		int numIngredient = 0;
		
		List<Integer> listeEmplacement=new ArrayList<Integer>(casesRemplies.keySet());
		Collections.sort(listeEmplacement);
		
		for (Integer emplacement : listeEmplacement) {
			numIngredient = casesRemplies.get(emplacement).getNumIngredient();

			if (numIngredient > dernierNumIngredientLu)
				uneSuite++;
			else
				uneSuite=1;
			
			suiteMax = Math.max(suiteMax, uneSuite);
			dernierNumIngredientLu = numIngredient;
		}

		estGagnant = suiteMax == 12;

		return suiteMax;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + idPlateau;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PlateauPizza other = (PlateauPizza) obj;
		if (idPlateau != other.idPlateau)
			return false;
		return true;
	}

}
